home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / text / edit / vim60src.lha / Vim / vim60 / src / farsi.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-08-19  |  36.7 KB  |  2,310 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * farsi.c: functions for Farsi language
  12.  *
  13.  * Included by main.c, when FEAT_FKMAP is defined.
  14.  */
  15.  
  16. static int toF_Xor_X_ __ARGS((int c));
  17. static int F_is_TyE __ARGS((int c));
  18. static int F_is_TyC_TyD __ARGS((int c));
  19. static int F_is_TyB_TyC_TyD __ARGS((int src, int offset));
  20. static int toF_TyB __ARGS((int c));
  21. static void put_curr_and_l_to_X __ARGS((int c));
  22. static void put_and_redo __ARGS((int c));
  23. static void chg_c_toX_orX __ARGS((void));
  24. static void chg_c_to_X_orX_ __ARGS((void));
  25. static void chg_c_to_X_or_X __ARGS((void));
  26. static void chg_l_to_X_orX_ __ARGS((void));
  27. static void chg_l_toXor_X __ARGS((void));
  28. static void chg_r_to_Xor_X_ __ARGS((void));
  29. static int toF_leading __ARGS((int c));
  30. static int toF_Rjoin __ARGS((int c));
  31. static int canF_Ljoin __ARGS((int c));
  32. static int canF_Rjoin __ARGS((int c));
  33. static int F_isterm __ARGS((int c));
  34. static int toF_ending __ARGS((int c));
  35. static void lrswapbuf __ARGS((char_u *buf, int len));
  36.  
  37. /*
  38. ** Convert the given Farsi character into a _X or _X_ type
  39. */
  40.     static int
  41. toF_Xor_X_(c)
  42.     int    c;
  43. {
  44.     int tempc;
  45.  
  46.     switch (c)
  47.     {
  48.     case BE:
  49.         return _BE;
  50.     case PE:
  51.         return _PE;
  52.     case TE:
  53.         return _TE;
  54.     case SE:
  55.         return _SE;
  56.     case JIM:
  57.         return _JIM;
  58.     case CHE:
  59.         return _CHE;
  60.     case HE_J:
  61.         return _HE_J;
  62.     case XE:
  63.         return _XE;
  64.     case SIN:
  65.         return _SIN;
  66.     case SHIN:
  67.         return _SHIN;
  68.     case SAD:
  69.         return _SAD;
  70.     case ZAD:
  71.         return _ZAD;
  72.     case AYN:
  73.         return _AYN;
  74.     case AYN_:
  75.         return _AYN_;
  76.     case GHAYN:
  77.         return _GHAYN;
  78.     case GHAYN_:
  79.         return _GHAYN_;
  80.     case FE:
  81.         return _FE;
  82.     case GHAF:
  83.         return _GHAF;
  84.     case KAF:
  85.         return _KAF;
  86.     case GAF:
  87.         return _GAF;
  88.     case LAM:
  89.         return _LAM;
  90.     case MIM:
  91.         return _MIM;
  92.     case NOON:
  93.         return _NOON;
  94.     case YE:
  95.     case YE_:
  96.         return _YE;
  97.     case YEE:
  98.     case YEE_:
  99.         return _YEE;
  100.     case IE:
  101.     case IE_:
  102.         return _IE;
  103.     case F_HE:
  104.         tempc = _HE;
  105.  
  106.         if (p_ri && (curwin->w_cursor.col+1 < STRLEN(ml_get_curline())))
  107.         {
  108.             inc_cursor();
  109.  
  110.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  111.             tempc = _HE_;
  112.  
  113.             dec_cursor();
  114.         }
  115.         if (!p_ri && STRLEN(ml_get_curline()))
  116.         {
  117.             dec_cursor();
  118.  
  119.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  120.             tempc = _HE_;
  121.  
  122.             inc_cursor();
  123.         }
  124.  
  125.         return tempc;
  126.     }
  127.     return 0;
  128. }
  129.  
  130. /*
  131. ** Convert the given Farsi character into Farsi capital character .
  132. */
  133.     int
  134. toF_TyA(c)
  135.     int    c ;
  136. {
  137.     switch (c)
  138.     {
  139.     case ALEF_:
  140.         return ALEF;
  141.     case ALEF_U_H_:
  142.         return ALEF_U_H;
  143.     case _BE:
  144.         return BE;
  145.     case _PE:
  146.         return PE;
  147.     case _TE:
  148.         return TE;
  149.     case _SE:
  150.         return SE;
  151.     case _JIM:
  152.         return JIM;
  153.     case _CHE:
  154.         return CHE;
  155.     case _HE_J:
  156.         return HE_J;
  157.     case _XE:
  158.         return XE;
  159.     case _SIN:
  160.         return SIN;
  161.     case _SHIN:
  162.         return SHIN;
  163.     case _SAD:
  164.         return SAD;
  165.     case _ZAD:
  166.         return ZAD;
  167.     case _AYN:
  168.     case AYN_:
  169.     case _AYN_:
  170.         return AYN;
  171.     case _GHAYN:
  172.     case GHAYN_:
  173.     case _GHAYN_:
  174.         return GHAYN;
  175.     case _FE:
  176.         return FE;
  177.     case _GHAF:
  178.         return GHAF;
  179. /* I am not sure what it is !!!        case _KAF_H: */
  180.     case _KAF:
  181.         return KAF;
  182.     case _GAF:
  183.         return GAF;
  184.     case _LAM:
  185.         return LAM;
  186.     case _MIM:
  187.         return MIM;
  188.     case _NOON:
  189.         return NOON;
  190.     case _YE:
  191.     case YE_:
  192.         return YE;
  193.     case _YEE:
  194.     case YEE_:
  195.         return YEE;
  196.     case TEE_:
  197.         return TEE;
  198.     case _IE:
  199.     case IE_:
  200.         return IE;
  201.     case _HE:
  202.     case _HE_:
  203.         return F_HE;
  204.     }
  205.     return c;
  206. }
  207.  
  208. /*
  209. ** Is the character under the cursor+offset in the given buffer a join type.
  210. ** That is a character that is combined with the others.
  211. ** Note: the offset is used only for command line buffer.
  212. */
  213.     static int
  214. F_is_TyB_TyC_TyD(src, offset)
  215.     int        src, offset;
  216. {
  217.     int        c;
  218.  
  219.     if (src == SRC_EDT)
  220.     c = gchar_cursor();
  221.     else
  222.     c = cmd_gchar(AT_CURSOR+offset);
  223.  
  224.     switch (c)
  225.     {
  226.     case _LAM:
  227.     case _BE:
  228.     case _PE:
  229.     case _TE:
  230.     case _SE:
  231.     case _JIM:
  232.     case _CHE:
  233.     case _HE_J:
  234.     case _XE:
  235.     case _SIN:
  236.     case _SHIN:
  237.     case _SAD:
  238.     case _ZAD:
  239.     case _TA:
  240.     case _ZA:
  241.     case _AYN:
  242.     case _AYN_:
  243.     case _GHAYN:
  244.     case _GHAYN_:
  245.     case _FE:
  246.     case _GHAF:
  247.     case _KAF:
  248.     case _KAF_H:
  249.     case _GAF:
  250.     case _MIM:
  251.     case _NOON:
  252.     case _YE:
  253.     case _YEE:
  254.     case _IE:
  255.     case _HE_:
  256.     case _HE:
  257.         return TRUE;
  258.     }
  259.     return FALSE;
  260. }
  261.  
  262. /*
  263. ** Is the Farsi character one of the terminating only type.
  264. */
  265.     static int
  266. F_is_TyE(c)
  267.     int        c;
  268. {
  269.     switch (c)
  270.     {
  271.     case ALEF_A:
  272.     case ALEF_D_H:
  273.     case DAL:
  274.     case ZAL:
  275.     case RE:
  276.     case ZE:
  277.     case JE:
  278.     case WAW:
  279.     case WAW_H:
  280.     case HAMZE:
  281.         return TRUE;
  282.     }
  283.     return FALSE;
  284. }
  285.  
  286. /*
  287. ** Is the Farsi character one of the none leading type.
  288. */
  289.     static int
  290. F_is_TyC_TyD(c)
  291.     int        c;
  292. {
  293.     switch (c)
  294.     {
  295.     case ALEF_:
  296.     case ALEF_U_H_:
  297.     case _AYN_:
  298.     case AYN_:
  299.     case _GHAYN_:
  300.     case GHAYN_:
  301.     case _HE_:
  302.     case YE_:
  303.     case IE_:
  304.     case TEE_:
  305.     case YEE_:
  306.         return TRUE;
  307.     }
  308.     return FALSE;
  309. }
  310.  
  311. /*
  312. ** Convert a none leading Farsi char into a leading type.
  313. */
  314.     static int
  315. toF_TyB(c)
  316.     int        c;
  317. {
  318.     switch (c)
  319.     {
  320.     case ALEF_:    return ALEF;
  321.     case ALEF_U_H_:        return ALEF_U_H;
  322.     case _AYN_:    return _AYN;
  323.     case AYN_:    return AYN;    /* exception - there are many of them */
  324.     case _GHAYN_:    return _GHAYN;
  325.     case GHAYN_:    return GHAYN;    /* exception - there are many of them */
  326.     case _HE_:    return _HE;
  327.     case YE_:    return YE;
  328.     case IE_:    return IE;
  329.     case TEE_:    return TEE;
  330.     case YEE_:    return YEE;
  331.     }
  332.     return c;
  333. }
  334.  
  335. /*
  336. ** Overwrite the current redo and cursor characters + left adjust
  337. */
  338.     static void
  339. put_curr_and_l_to_X(c)
  340.     int          c;
  341. {
  342.     int    tempc;
  343.  
  344.     if (curwin->w_p_rl && p_ri)
  345.     return;
  346.  
  347.     if ( (curwin->w_cursor.col < STRLEN(ml_get_curline())))
  348.     {
  349.     if ((p_ri && curwin->w_cursor.col) || !p_ri)
  350.     {
  351.         if (p_ri)
  352.         dec_cursor();
  353.         else
  354.         inc_cursor();
  355.  
  356.         if (F_is_TyC_TyD((tempc = gchar_cursor())))
  357.         {
  358.         pchar_cursor(toF_TyB(tempc));
  359.         AppendCharToRedobuff(K_BS);
  360.         AppendCharToRedobuff(tempc);
  361.         }
  362.  
  363.         if (p_ri)
  364.         inc_cursor();
  365.         else
  366.         dec_cursor();
  367.     }
  368.     }
  369.  
  370.     put_and_redo(c);
  371. }
  372.  
  373.     static void
  374. put_and_redo(c)
  375.     int c;
  376. {
  377.     pchar_cursor(c);
  378.     AppendCharToRedobuff(K_BS);
  379.     AppendCharToRedobuff(c);
  380. }
  381.  
  382. /*
  383. ** Change the char. under the cursor to a X_ or X type
  384. */
  385.     static void
  386. chg_c_toX_orX()
  387. {
  388.     int    tempc, curc;
  389.  
  390.     switch ((curc = gchar_cursor()))
  391.     {
  392.     case _BE:
  393.         tempc = BE;
  394.         break;
  395.     case _PE:
  396.         tempc = PE;
  397.         break;
  398.     case _TE:
  399.         tempc = TE;
  400.         break;
  401.     case _SE:
  402.         tempc = SE;
  403.         break;
  404.     case _JIM:
  405.         tempc = JIM;
  406.         break;
  407.     case _CHE:
  408.         tempc = CHE;
  409.         break;
  410.     case _HE_J:
  411.         tempc = HE_J;
  412.         break;
  413.     case _XE:
  414.         tempc = XE;
  415.         break;
  416.     case _SIN:
  417.         tempc = SIN;
  418.         break;
  419.     case _SHIN:
  420.         tempc = SHIN;
  421.         break;
  422.     case _SAD:
  423.         tempc = SAD;
  424.         break;
  425.     case _ZAD:
  426.         tempc = ZAD;
  427.         break;
  428.     case _FE:
  429.         tempc = FE;
  430.         break;
  431.     case _GHAF:
  432.         tempc = GHAF;
  433.         break;
  434.     case _KAF_H:
  435.     case _KAF:
  436.         tempc = KAF;
  437.         break;
  438.     case _GAF:
  439.         tempc = GAF;
  440.         break;
  441.     case _AYN:
  442.         tempc = AYN;
  443.         break;
  444.     case _AYN_:
  445.         tempc = AYN_;
  446.         break;
  447.     case _GHAYN:
  448.         tempc = GHAYN;
  449.         break;
  450.     case _GHAYN_:
  451.         tempc = GHAYN_;
  452.         break;
  453.     case _LAM:
  454.         tempc = LAM;
  455.         break;
  456.     case _MIM:
  457.         tempc = MIM;
  458.         break;
  459.     case _NOON:
  460.         tempc = NOON;
  461.         break;
  462.     case _HE:
  463.     case _HE_:
  464.         tempc = F_HE;
  465.         break;
  466.     case _YE:
  467.     case _IE:
  468.     case _YEE:
  469.         if (p_ri)
  470.         {
  471.             inc_cursor();
  472.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  473.                 tempc = (curc == _YE ? YE_ :
  474.                 (curc == _IE ? IE_ : YEE_));
  475.             else
  476.                 tempc = (curc == _YE ? YE :
  477.                 (curc == _IE ? IE : YEE));
  478.             dec_cursor();
  479.         }
  480.         else
  481.         {
  482.             if (curwin->w_cursor.col)
  483.             {
  484.             dec_cursor();
  485.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  486.                 tempc = (curc == _YE ? YE_ :
  487.                 (curc == _IE ? IE_ : YEE_));
  488.             else
  489.                 tempc = (curc == _YE ? YE :
  490.                 (curc == _IE ? IE : YEE));
  491.             inc_cursor();
  492.             }
  493.             else
  494.                 tempc = (curc == _YE ? YE :
  495.                 (curc == _IE ? IE : YEE));
  496.         }
  497.         break;
  498.     default:
  499.         tempc = 0;
  500.     }
  501.  
  502.     if (tempc)
  503.     put_and_redo(tempc);
  504. }
  505.  
  506. /*
  507. ** Change the char. under the cursor to a _X_ or X_ type
  508. */
  509.  
  510.     static void
  511. chg_c_to_X_orX_()
  512. {
  513.     int    tempc;
  514.  
  515.     switch (gchar_cursor())
  516.     {
  517.     case ALEF:
  518.         tempc = ALEF_;
  519.         break;
  520.     case ALEF_U_H:
  521.         tempc = ALEF_U_H_;
  522.         break;
  523.     case _AYN:
  524.         tempc = _AYN_;
  525.         break;
  526.     case AYN:
  527.         tempc = AYN_;
  528.         break;
  529.     case _GHAYN:
  530.         tempc = _GHAYN_;
  531.         break;
  532.     case GHAYN:
  533.         tempc = GHAYN_;
  534.         break;
  535.     case _HE:
  536.         tempc = _HE_;
  537.         break;
  538.     case YE:
  539.         tempc = YE_;
  540.         break;
  541.     case IE:
  542.         tempc = IE_;
  543.         break;
  544.     case TEE:
  545.         tempc = TEE_;
  546.         break;
  547.     case YEE:
  548.         tempc = YEE_;
  549.         break;
  550.     default:
  551.         tempc = 0;
  552.     }
  553.  
  554.     if (tempc)
  555.     put_and_redo(tempc);
  556. }
  557.  
  558. /*
  559. ** Change the char. under the cursor to a _X_ or _X type
  560. */
  561.     static void
  562. chg_c_to_X_or_X ()
  563. {
  564.     int    tempc;
  565.  
  566.     tempc = gchar_cursor();
  567.  
  568.     if (curwin->w_cursor.col+1 < STRLEN(ml_get_curline()))
  569.     {
  570.     inc_cursor();
  571.  
  572.     if ((tempc == F_HE) && (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)))
  573.     {
  574.         tempc = _HE_;
  575.  
  576.         dec_cursor();
  577.  
  578.         put_and_redo(tempc);
  579.         return;
  580.     }
  581.  
  582.     dec_cursor();
  583.     }
  584.  
  585.     if ((tempc = toF_Xor_X_(tempc)) != 0)
  586.     put_and_redo(tempc);
  587. }
  588.  
  589. /*
  590. ** Change the character left to the cursor to a _X_ or X_ type
  591. */
  592.     static void
  593. chg_l_to_X_orX_ ()
  594. {
  595.     int    tempc;
  596.  
  597.     if (!curwin->w_cursor.col &&
  598.     (curwin->w_cursor.col+1 == STRLEN(ml_get_curline())))
  599.     return;
  600.  
  601.     if (!curwin->w_cursor.col && p_ri)
  602.     return;
  603.  
  604.     if (p_ri)
  605.     dec_cursor();
  606.     else
  607.     inc_cursor();
  608.  
  609.     switch (gchar_cursor())
  610.     {
  611.     case ALEF:
  612.         tempc = ALEF_;
  613.         break;
  614.     case ALEF_U_H:
  615.         tempc = ALEF_U_H_;
  616.         break;
  617.     case _AYN:
  618.         tempc = _AYN_;
  619.         break;
  620.     case AYN:
  621.         tempc = AYN_;
  622.         break;
  623.     case _GHAYN:
  624.         tempc = _GHAYN_;
  625.         break;
  626.     case GHAYN:
  627.         tempc = GHAYN_;
  628.         break;
  629.     case _HE:
  630.         tempc = _HE_;
  631.         break;
  632.     case YE:
  633.         tempc = YE_;
  634.         break;
  635.     case IE:
  636.         tempc = IE_;
  637.         break;
  638.     case TEE:
  639.         tempc = TEE_;
  640.         break;
  641.     case YEE:
  642.         tempc = YEE_;
  643.         break;
  644.     default:
  645.         tempc = 0;
  646.     }
  647.  
  648.     if (tempc)
  649.     put_and_redo(tempc);
  650.  
  651.     if (p_ri)
  652.     inc_cursor();
  653.     else
  654.     dec_cursor();
  655. }
  656.  
  657. /*
  658. ** Change the charcter left to the cursor to a X or _X type
  659. */
  660.  
  661.     static void
  662. chg_l_toXor_X ()
  663. {
  664.     int    tempc;
  665.  
  666.     if (!curwin->w_cursor.col &&
  667.     (curwin->w_cursor.col+1 == STRLEN(ml_get_curline())))
  668.     return;
  669.  
  670.     if (!curwin->w_cursor.col && p_ri)
  671.     return;
  672.  
  673.     if (p_ri)
  674.     dec_cursor();
  675.     else
  676.     inc_cursor();
  677.  
  678.     switch (gchar_cursor())
  679.     {
  680.     case ALEF_:
  681.         tempc = ALEF;
  682.         break;
  683.     case ALEF_U_H_:
  684.         tempc = ALEF_U_H;
  685.         break;
  686.     case _AYN_:
  687.         tempc = _AYN;
  688.         break;
  689.     case AYN_:
  690.         tempc = AYN;
  691.         break;
  692.     case _GHAYN_:
  693.         tempc = _GHAYN;
  694.         break;
  695.     case GHAYN_:
  696.         tempc = GHAYN;
  697.         break;
  698.     case _HE_:
  699.         tempc = _HE;
  700.         break;
  701.     case YE_:
  702.         tempc = YE;
  703.         break;
  704.     case IE_:
  705.         tempc = IE;
  706.         break;
  707.     case TEE_:
  708.         tempc = TEE;
  709.         break;
  710.     case YEE_:
  711.         tempc = YEE;
  712.         break;
  713.     default:
  714.         tempc = 0;
  715.     }
  716.  
  717.     if (tempc)
  718.     put_and_redo(tempc);
  719.  
  720.     if (p_ri)
  721.     inc_cursor();
  722.     else
  723.     dec_cursor();
  724. }
  725.  
  726. /*
  727. ** Change the charcter right to the cursor to a _X or _X_ type
  728. */
  729.  
  730.     static void
  731. chg_r_to_Xor_X_()
  732. {
  733.     int tempc, c;
  734.  
  735.     if (curwin->w_cursor.col)
  736.     {
  737.     if (!p_ri)
  738.         dec_cursor();
  739.  
  740.     tempc = gchar_cursor();
  741.  
  742.     if ((c = toF_Xor_X_(tempc)) != 0)
  743.         put_and_redo(c);
  744.  
  745.     if (!p_ri)
  746.         inc_cursor();
  747.  
  748.     }
  749. }
  750.  
  751. /*
  752. ** Map Farsi keyboard when in fkmap mode.
  753. */
  754.  
  755.     int
  756. fkmap(c)
  757.     int c;
  758. {
  759.     int        tempc;
  760.     static int    revins;
  761.  
  762.     if (vim_isdigit(c) || ((c == '.' || c == '+' || c == '-' ||
  763.     c == '^' || c == '%' || c == '#' || c == '=')  && revins))
  764.     {
  765.     if (!revins)
  766.     {
  767.         if (curwin->w_cursor.col)
  768.         {
  769.         if (!p_ri)
  770.             dec_cursor();
  771.  
  772.             chg_c_toX_orX ();
  773.             chg_l_toXor_X ();
  774.  
  775.         if (!p_ri)
  776.             inc_cursor();
  777.         }
  778.     }
  779.  
  780.     arrow_used = TRUE;
  781.     (void)stop_arrow();
  782.  
  783.     if (!curwin->w_p_rl && revins)
  784.         inc_cursor();
  785.  
  786.     ++revins;
  787.     p_ri=1;
  788.     }
  789.     else
  790.     {
  791.     if (revins)
  792.     {
  793.         arrow_used = TRUE;
  794.         (void)stop_arrow();
  795.  
  796.         revins = 0;
  797.         if (curwin->w_p_rl)
  798.         {
  799.         while ((F_isdigit(gchar_cursor())
  800.                 || (gchar_cursor() == F_PERIOD
  801.                 || gchar_cursor() == F_PLUS
  802.                 || gchar_cursor() == F_MINUS
  803.                 || gchar_cursor() == F_MUL
  804.                 || gchar_cursor() == F_DIVIDE
  805.                 || gchar_cursor() == F_PERCENT
  806.                 || gchar_cursor() == F_EQUALS))
  807.             && gchar_cursor() != NUL)
  808.             ++curwin->w_cursor.col;
  809.         }
  810.         else
  811.         {
  812.         if (curwin->w_cursor.col)
  813.             while ((F_isdigit(gchar_cursor())
  814.                 || (gchar_cursor() == F_PERIOD
  815.                 || gchar_cursor() == F_PLUS
  816.                 || gchar_cursor() == F_MINUS
  817.                 || gchar_cursor() == F_MUL
  818.                 || gchar_cursor() == F_DIVIDE
  819.                 || gchar_cursor() == F_PERCENT
  820.                 || gchar_cursor() == F_EQUALS))
  821.                 && --curwin->w_cursor.col)
  822.             ;
  823.  
  824.         if (!F_isdigit(gchar_cursor()))
  825.             ++curwin->w_cursor.col;
  826.         }
  827.     }
  828.     }
  829.  
  830.     if (!revins)
  831.     {
  832.     if (curwin->w_p_rl)
  833.         p_ri=0;
  834.     if (!curwin->w_p_rl)
  835.         p_ri=1;
  836.     }
  837.  
  838.     if ((c < 0x100) && (isalpha(c) || c == '&' ||   c == '^' ||    c == ';' ||
  839.                 c == '\''||    c == ',' || c == '[' ||
  840.                 c == ']' ||    c == '{' || c == '}'    ))
  841.     chg_r_to_Xor_X_();
  842.  
  843.     tempc = 0;
  844.  
  845.     switch (c)
  846.     {
  847.     case '`':
  848.     case ' ':
  849.     case '.':
  850.     case '!':
  851.     case '"':
  852.     case '$':
  853.     case '%':
  854.     case '^':
  855.     case '&':
  856.     case '/':
  857.     case '(':
  858.     case ')':
  859.     case '=':
  860.     case '\\':
  861.     case '?':
  862.     case '+':
  863.     case '-':
  864.     case '_':
  865.     case '*':
  866.     case ':':
  867.     case '#':
  868.     case '~':
  869.     case '@':
  870.     case '<':
  871.     case '>':
  872.     case '{':
  873.     case '}':
  874.     case '|':
  875.     case '0':
  876.     case '1':
  877.     case '2':
  878.     case '3':
  879.     case '4':
  880.     case '5':
  881.     case '6':
  882.     case '7':
  883.     case '8':
  884.     case '9':
  885.     case 'B':
  886.     case 'E':
  887.     case 'F':
  888.     case 'H':
  889.     case 'I':
  890.     case 'K':
  891.     case 'L':
  892.     case 'M':
  893.     case 'O':
  894.     case 'P':
  895.     case 'Q':
  896.     case 'R':
  897.     case 'T':
  898.     case 'U':
  899.     case 'W':
  900.     case 'Y':
  901.     case  NL:
  902.     case  TAB:
  903.  
  904.         if (p_ri && c == NL && curwin->w_cursor.col)
  905.         {
  906.         /*
  907.         ** If the char before the cursor is _X_ or X_ do not change
  908.         ** the one under the cursor with X type.
  909.         */
  910.  
  911.         dec_cursor();
  912.  
  913.         if (F_isalpha(gchar_cursor()))
  914.         {
  915.             inc_cursor();
  916.             return NL;
  917.         }
  918.  
  919.         inc_cursor();
  920.         }
  921.  
  922.         if (!p_ri)
  923.         if (!curwin->w_cursor.col)
  924.         {
  925.         switch (c)
  926.         {
  927.             case '0':    return FARSI_0;
  928.             case '1':    return FARSI_1;
  929.             case '2':    return FARSI_2;
  930.             case '3':    return FARSI_3;
  931.             case '4':    return FARSI_4;
  932.             case '5':    return FARSI_5;
  933.             case '6':    return FARSI_6;
  934.             case '7':    return FARSI_7;
  935.             case '8':    return FARSI_8;
  936.             case '9':    return FARSI_9;
  937.             case 'B':    return F_PSP;
  938.             case 'E':    return JAZR_N;
  939.             case 'F':    return ALEF_D_H;
  940.             case 'H':    return ALEF_A;
  941.             case 'I':    return TASH;
  942.             case 'K':    return F_LQUOT;
  943.             case 'L':    return F_RQUOT;
  944.             case 'M':    return HAMZE;
  945.             case 'O':    return '[';
  946.             case 'P':    return ']';
  947.             case 'Q':    return OO;
  948.             case 'R':    return MAD_N;
  949.             case 'T':    return OW;
  950.             case 'U':    return MAD;
  951.             case 'W':    return OW_OW;
  952.             case 'Y':    return JAZR;
  953.             case '`':    return F_PCN;
  954.             case '!':    return F_EXCL;
  955.             case '@':    return F_COMMA;
  956.             case '#':    return F_DIVIDE;
  957.             case '$':    return F_CURRENCY;
  958.             case '%':    return F_PERCENT;
  959.             case '^':    return F_MUL;
  960.             case '&':    return F_BCOMMA;
  961.             case '*':    return F_STAR;
  962.             case '(':    return F_LPARENT;
  963.             case ')':    return F_RPARENT;
  964.             case '-':    return F_MINUS;
  965.             case '_':    return F_UNDERLINE;
  966.             case '=':    return F_EQUALS;
  967.             case '+':    return F_PLUS;
  968.             case '\\':    return F_BSLASH;
  969.             case '|':    return F_PIPE;
  970.             case ':':    return F_DCOLON;
  971.             case '"':    return F_SEMICOLON;
  972.             case '.':    return F_PERIOD;
  973.             case '/':    return F_SLASH;
  974.             case '<':    return F_LESS;
  975.             case '>':    return F_GREATER;
  976.             case '?':    return F_QUESTION;
  977.             case ' ':    return F_BLANK;
  978.         }
  979.         break;
  980.         }
  981.         if (!p_ri)
  982.         dec_cursor();
  983.  
  984.         switch ((tempc = gchar_cursor()))
  985.         {
  986.         case _BE:
  987.         case _PE:
  988.         case _TE:
  989.         case _SE:
  990.         case _JIM:
  991.         case _CHE:
  992.         case _HE_J:
  993.         case _XE:
  994.         case _SIN:
  995.         case _SHIN:
  996.         case _SAD:
  997.         case _ZAD:
  998.         case _FE:
  999.         case _GHAF:
  1000.         case _KAF:
  1001.         case _KAF_H:
  1002.         case _GAF:
  1003.         case _LAM:
  1004.         case _MIM:
  1005.         case _NOON:
  1006.         case _HE:
  1007.         case _HE_:
  1008.         case _TA:
  1009.         case _ZA:
  1010.             put_curr_and_l_to_X(toF_TyA(tempc));
  1011.             break;
  1012.         case _AYN:
  1013.         case _AYN_:
  1014.  
  1015.             if (!p_ri)
  1016.                 if (!curwin->w_cursor.col)
  1017.                 {
  1018.                 put_curr_and_l_to_X(AYN);
  1019.                 break;
  1020.                 }
  1021.  
  1022.             if (p_ri)
  1023.                 inc_cursor();
  1024.             else
  1025.                 dec_cursor();
  1026.  
  1027.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1028.                 tempc = AYN_;
  1029.             else
  1030.                 tempc = AYN;
  1031.  
  1032.             if (p_ri)
  1033.                 dec_cursor();
  1034.             else
  1035.                 inc_cursor();
  1036.  
  1037.             put_curr_and_l_to_X(tempc);
  1038.  
  1039.             break;
  1040.         case _GHAYN:
  1041.         case _GHAYN_:
  1042.  
  1043.             if (!p_ri)
  1044.                 if (!curwin->w_cursor.col)
  1045.                 {
  1046.                 put_curr_and_l_to_X(GHAYN);
  1047.                 break;
  1048.                 }
  1049.  
  1050.             if (p_ri)
  1051.                 inc_cursor();
  1052.             else
  1053.                 dec_cursor();
  1054.  
  1055.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1056.                 tempc = GHAYN_;
  1057.             else
  1058.                 tempc = GHAYN;
  1059.  
  1060.             if (p_ri)
  1061.                 dec_cursor();
  1062.             else
  1063.                 inc_cursor();
  1064.  
  1065.             put_curr_and_l_to_X(tempc);
  1066.             break;
  1067.         case _YE:
  1068.         case _IE:
  1069.         case _YEE:
  1070.             if (!p_ri)
  1071.                 if (!curwin->w_cursor.col)
  1072.                 {
  1073.                 put_curr_and_l_to_X((tempc == _YE ? YE :
  1074.                         (tempc == _IE ? IE : YEE)));
  1075.                 break;
  1076.                 }
  1077.  
  1078.             if (p_ri)
  1079.                 inc_cursor();
  1080.             else
  1081.                 dec_cursor();
  1082.  
  1083.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1084.                 tempc = (tempc == _YE ? YE_ :
  1085.                     (tempc == _IE ? IE_ : YEE_));
  1086.             else
  1087.                 tempc = (tempc == _YE ? YE :
  1088.                     (tempc == _IE ? IE : YEE));
  1089.  
  1090.             if (p_ri)
  1091.                 dec_cursor();
  1092.             else
  1093.                 inc_cursor();
  1094.  
  1095.             put_curr_and_l_to_X(tempc);
  1096.             break;
  1097.         }
  1098.  
  1099.         if (!p_ri)
  1100.             inc_cursor();
  1101.  
  1102.         tempc = 0;
  1103.  
  1104.         switch (c)
  1105.         {
  1106.             case '0':    return FARSI_0;
  1107.             case '1':    return FARSI_1;
  1108.             case '2':    return FARSI_2;
  1109.             case '3':    return FARSI_3;
  1110.             case '4':    return FARSI_4;
  1111.             case '5':    return FARSI_5;
  1112.             case '6':    return FARSI_6;
  1113.             case '7':    return FARSI_7;
  1114.             case '8':    return FARSI_8;
  1115.             case '9':    return FARSI_9;
  1116.             case 'B':    return F_PSP;
  1117.             case 'E':    return JAZR_N;
  1118.             case 'F':    return ALEF_D_H;
  1119.             case 'H':    return ALEF_A;
  1120.             case 'I':    return TASH;
  1121.             case 'K':    return F_LQUOT;
  1122.             case 'L':    return F_RQUOT;
  1123.             case 'M':    return HAMZE;
  1124.             case 'O':    return '[';
  1125.             case 'P':    return ']';
  1126.             case 'Q':    return OO;
  1127.             case 'R':    return MAD_N;
  1128.             case 'T':    return OW;
  1129.             case 'U':    return MAD;
  1130.             case 'W':    return OW_OW;
  1131.             case 'Y':    return JAZR;
  1132.             case '`':    return F_PCN;
  1133.             case '!':    return F_EXCL;
  1134.             case '@':    return F_COMMA;
  1135.             case '#':    return F_DIVIDE;
  1136.             case '$':    return F_CURRENCY;
  1137.             case '%':    return F_PERCENT;
  1138.             case '^':    return F_MUL;
  1139.             case '&':    return F_BCOMMA;
  1140.             case '*':    return F_STAR;
  1141.             case '(':    return F_LPARENT;
  1142.             case ')':    return F_RPARENT;
  1143.             case '-':    return F_MINUS;
  1144.             case '_':    return F_UNDERLINE;
  1145.             case '=':    return F_EQUALS;
  1146.             case '+':    return F_PLUS;
  1147.             case '\\':    return F_BSLASH;
  1148.             case '|':    return F_PIPE;
  1149.             case ':':    return F_DCOLON;
  1150.             case '"':    return F_SEMICOLON;
  1151.             case '.':    return F_PERIOD;
  1152.             case '/':    return F_SLASH;
  1153.             case '<':    return F_LESS;
  1154.             case '>':    return F_GREATER;
  1155.             case '?':    return F_QUESTION;
  1156.             case ' ':    return F_BLANK;
  1157.         }
  1158.         break;
  1159.  
  1160.     case 'a':
  1161.         tempc = _SHIN;
  1162.         break;
  1163.     case 'A':
  1164.         tempc = WAW_H;
  1165.         break;
  1166.     case 'b':
  1167.         tempc = ZAL;
  1168.         break;
  1169.     case 'c':
  1170.         tempc = ZE;
  1171.         break;
  1172.     case 'C':
  1173.         tempc = JE;
  1174.         break;
  1175.     case 'd':
  1176.         tempc = _YE;
  1177.         break;
  1178.     case 'D':
  1179.         tempc = _YEE;
  1180.         break;
  1181.     case 'e':
  1182.         tempc = _SE;
  1183.         break;
  1184.     case 'f':
  1185.         tempc = _BE;
  1186.         break;
  1187.     case 'g':
  1188.         tempc = _LAM;
  1189.         break;
  1190.     case 'G':
  1191.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1192.         {
  1193.  
  1194.         if (gchar_cursor() == _LAM)
  1195.             chg_c_toX_orX ();
  1196.         else
  1197.             if (p_ri)
  1198.             chg_c_to_X_or_X ();
  1199.         }
  1200.  
  1201.         if (!p_ri)
  1202.         if (!curwin->w_cursor.col)
  1203.             return ALEF_U_H;
  1204.  
  1205.         if (!p_ri)
  1206.         dec_cursor();
  1207.  
  1208.         if (gchar_cursor() == _LAM)
  1209.         {
  1210.         chg_c_toX_orX ();
  1211.         chg_l_toXor_X ();
  1212.             tempc = ALEF_U_H;
  1213.         }
  1214.         else
  1215.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1216.         {
  1217.             tempc = ALEF_U_H_;
  1218.             chg_l_toXor_X ();
  1219.         }
  1220.         else
  1221.             tempc = ALEF_U_H;
  1222.  
  1223.         if (!p_ri)
  1224.         inc_cursor();
  1225.  
  1226.         return tempc;
  1227.     case 'h':
  1228.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1229.         {
  1230.         if (p_ri)
  1231.             chg_c_to_X_or_X ();
  1232.  
  1233.         }
  1234.  
  1235.         if (!p_ri)
  1236.         if (!curwin->w_cursor.col)
  1237.             return ALEF;
  1238.  
  1239.         if (!p_ri)
  1240.         dec_cursor();
  1241.  
  1242.         if (gchar_cursor() == _LAM)
  1243.         {
  1244.         chg_l_toXor_X();
  1245.         del_char(FALSE);
  1246.         AppendCharToRedobuff(K_BS);
  1247.  
  1248.         if (!p_ri)
  1249.             dec_cursor();
  1250.  
  1251.             tempc = LA;
  1252.         }
  1253.         else
  1254.         {
  1255.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1256.         {
  1257.             tempc = ALEF_;
  1258.             chg_l_toXor_X ();
  1259.         }
  1260.         else
  1261.             tempc = ALEF;
  1262.         }
  1263.  
  1264.         if (!p_ri)
  1265.         inc_cursor();
  1266.  
  1267.         return tempc;
  1268.     case 'i':
  1269.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1270.         {
  1271.         if (!p_ri && !F_is_TyE(tempc))
  1272.             chg_c_to_X_orX_ ();
  1273.         if (p_ri)
  1274.             chg_c_to_X_or_X ();
  1275.  
  1276.         }
  1277.  
  1278.         if (!p_ri && !curwin->w_cursor.col)
  1279.         return _HE;
  1280.  
  1281.         if (!p_ri)
  1282.         dec_cursor();
  1283.  
  1284.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1285.             tempc = _HE_;
  1286.         else
  1287.             tempc = _HE;
  1288.  
  1289.         if (!p_ri)
  1290.         inc_cursor();
  1291.         break;
  1292.     case 'j':
  1293.         tempc = _TE;
  1294.         break;
  1295.     case 'J':
  1296.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1297.         {
  1298.         if (p_ri)
  1299.             chg_c_to_X_or_X ();
  1300.  
  1301.         }
  1302.  
  1303.         if (!p_ri)
  1304.         if (!curwin->w_cursor.col)
  1305.             return TEE;
  1306.  
  1307.         if (!p_ri)
  1308.         dec_cursor();
  1309.  
  1310.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1311.         {
  1312.             tempc = TEE_;
  1313.         chg_l_toXor_X ();
  1314.         }
  1315.         else
  1316.             tempc = TEE;
  1317.  
  1318.         if (!p_ri)
  1319.         inc_cursor();
  1320.  
  1321.         return tempc;
  1322.     case 'k':
  1323.         tempc = _NOON;
  1324.         break;
  1325.     case 'l':
  1326.         tempc = _MIM;
  1327.         break;
  1328.     case 'm':
  1329.         tempc = _PE;
  1330.         break;
  1331.     case 'n':
  1332.     case 'N':
  1333.         tempc = DAL;
  1334.         break;
  1335.     case 'o':
  1336.         tempc = _XE;
  1337.         break;
  1338.     case 'p':
  1339.         tempc = _HE_J;
  1340.         break;
  1341.     case 'q':
  1342.         tempc = _ZAD;
  1343.         break;
  1344.     case 'r':
  1345.         tempc = _GHAF;
  1346.         break;
  1347.     case 's':
  1348.         tempc = _SIN;
  1349.         break;
  1350.     case 'S':
  1351.         tempc = _IE;
  1352.         break;
  1353.     case 't':
  1354.         tempc = _FE;
  1355.         break;
  1356.     case 'u':
  1357.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1358.         {
  1359.             if (!p_ri && !F_is_TyE(tempc))
  1360.             chg_c_to_X_orX_ ();
  1361.             if (p_ri)
  1362.             chg_c_to_X_or_X ();
  1363.  
  1364.         }
  1365.  
  1366.         if (!p_ri && !curwin->w_cursor.col)
  1367.             return _AYN;
  1368.  
  1369.         if (!p_ri)
  1370.             dec_cursor();
  1371.  
  1372.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1373.             tempc = _AYN_;
  1374.         else
  1375.             tempc = _AYN;
  1376.  
  1377.         if (!p_ri)
  1378.             inc_cursor();
  1379.         break;
  1380.     case 'v':
  1381.     case 'V':
  1382.         tempc = RE;
  1383.         break;
  1384.     case 'w':
  1385.         tempc = _SAD;
  1386.         break;
  1387.     case 'x':
  1388.     case 'X':
  1389.         tempc = _TA;
  1390.         break;
  1391.     case 'y':
  1392.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1393.         {
  1394.         if (!p_ri && !F_is_TyE(tempc))
  1395.             chg_c_to_X_orX_ ();
  1396.         if (p_ri)
  1397.             chg_c_to_X_or_X ();
  1398.  
  1399.         }
  1400.  
  1401.         if (!p_ri && !curwin->w_cursor.col)
  1402.         return _GHAYN;
  1403.  
  1404.         if (!p_ri)
  1405.         dec_cursor();
  1406.  
  1407.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1408.         tempc = _GHAYN_;
  1409.         else
  1410.         tempc = _GHAYN;
  1411.  
  1412.         if (!p_ri)
  1413.         inc_cursor();
  1414.  
  1415.         break;
  1416.     case 'z':
  1417.         tempc = _ZA;
  1418.         break;
  1419.     case 'Z':
  1420.         tempc = _KAF_H;
  1421.         break;
  1422.     case ';':
  1423.         tempc = _KAF;
  1424.         break;
  1425.     case '\'':
  1426.         tempc = _GAF;
  1427.         break;
  1428.     case ',':
  1429.         tempc = WAW;
  1430.         break;
  1431.     case '[':
  1432.         tempc = _JIM;
  1433.         break;
  1434.     case ']':
  1435.         tempc = _CHE;
  1436.         break;
  1437.     }
  1438.  
  1439.     if ((F_isalpha(tempc) || F_isdigit(tempc)))
  1440.     {
  1441.     if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1442.         {
  1443.         if (!p_ri && !F_is_TyE(tempc))
  1444.         chg_c_to_X_orX_ ();
  1445.         if (p_ri)
  1446.         chg_c_to_X_or_X ();
  1447.     }
  1448.  
  1449.     if (curwin->w_cursor.col)
  1450.     {
  1451.         if (!p_ri)
  1452.         dec_cursor();
  1453.  
  1454.         if (F_is_TyE(tempc))
  1455.         chg_l_toXor_X ();
  1456.         else
  1457.         chg_l_to_X_orX_ ();
  1458.  
  1459.         if (!p_ri)
  1460.         inc_cursor();
  1461.     }
  1462.     }
  1463.     if (tempc)
  1464.     return tempc;
  1465.     return c;
  1466. }
  1467.  
  1468. /*
  1469. ** Convert a none leading Farsi char into a leading type.
  1470. */
  1471.     static int
  1472. toF_leading(c)
  1473.     int        c;
  1474. {
  1475.     switch (c)
  1476.     {
  1477.     case ALEF_:    return ALEF;
  1478.     case ALEF_U_H_:        return ALEF_U_H;
  1479.     case BE:    return _BE;
  1480.     case PE:    return _PE;
  1481.     case TE:    return _TE;
  1482.     case SE:    return _SE;
  1483.     case JIM:   return _JIM;
  1484.     case CHE:   return _CHE;
  1485.     case HE_J:  return _HE_J;
  1486.     case XE:    return _XE;
  1487.     case SIN:   return _SIN;
  1488.     case SHIN:  return _SHIN;
  1489.     case SAD:   return _SAD;
  1490.     case ZAD:   return _ZAD;
  1491.  
  1492.     case AYN:
  1493.     case AYN_:
  1494.     case _AYN_: return _AYN;
  1495.  
  1496.     case GHAYN:
  1497.     case GHAYN_:
  1498.     case _GHAYN_:    return _GHAYN;
  1499.  
  1500.     case FE:    return _FE;
  1501.     case GHAF:  return _GHAF;
  1502.     case KAF:   return _KAF;
  1503.     case GAF:   return _GAF;
  1504.     case LAM:   return _LAM;
  1505.     case MIM:   return _MIM;
  1506.     case NOON:  return _NOON;
  1507.  
  1508.     case _HE_:
  1509.     case F_HE:    return _HE;
  1510.  
  1511.     case YE:
  1512.     case YE_:    return _YE;
  1513.  
  1514.     case IE_:
  1515.     case IE:    return _IE;
  1516.  
  1517.     case YEE:
  1518.     case YEE_:    return _YEE;
  1519.     }
  1520.     return c;
  1521. }
  1522.  
  1523. /*
  1524. ** Convert a given Farsi char into right joining type.
  1525. */
  1526.     static int
  1527. toF_Rjoin(c)
  1528.     int        c;
  1529. {
  1530.     switch (c)
  1531.     {
  1532.     case ALEF:  return ALEF_;
  1533.     case ALEF_U_H:    return ALEF_U_H_;
  1534.     case BE:    return _BE;
  1535.     case PE:    return _PE;
  1536.     case TE:    return _TE;
  1537.     case SE:    return _SE;
  1538.     case JIM:   return _JIM;
  1539.     case CHE:   return _CHE;
  1540.     case HE_J:  return _HE_J;
  1541.     case XE:    return _XE;
  1542.     case SIN:   return _SIN;
  1543.     case SHIN:  return _SHIN;
  1544.     case SAD:   return _SAD;
  1545.     case ZAD:   return _ZAD;
  1546.  
  1547.     case AYN:
  1548.     case AYN_:
  1549.     case _AYN:  return _AYN_;
  1550.  
  1551.     case GHAYN:
  1552.     case GHAYN_:
  1553.     case _GHAYN_:    return _GHAYN_;
  1554.  
  1555.     case FE:    return _FE;
  1556.     case GHAF:  return _GHAF;
  1557.     case KAF:   return _KAF;
  1558.     case GAF:   return _GAF;
  1559.     case LAM:   return _LAM;
  1560.     case MIM:   return _MIM;
  1561.     case NOON:  return _NOON;
  1562.  
  1563.     case _HE:
  1564.     case F_HE:    return _HE_;
  1565.  
  1566.     case YE:
  1567.     case YE_:    return _YE;
  1568.  
  1569.     case IE_:
  1570.     case IE:    return _IE;
  1571.  
  1572.     case TEE:    return TEE_;
  1573.  
  1574.     case YEE:
  1575.     case YEE_:    return _YEE;
  1576.     }
  1577.     return c;
  1578. }
  1579.  
  1580. /*
  1581. ** Can a given Farsi character join via its left edj.
  1582. */
  1583.     static int
  1584. canF_Ljoin(c)
  1585.     int    c;
  1586. {
  1587.     switch (c)
  1588.     {
  1589.     case _BE:
  1590.     case BE:
  1591.     case PE:
  1592.     case _PE:
  1593.     case TE:
  1594.     case _TE:
  1595.     case SE:
  1596.     case _SE:
  1597.     case JIM:
  1598.     case _JIM:
  1599.     case CHE:
  1600.     case _CHE:
  1601.     case HE_J:
  1602.     case _HE_J:
  1603.     case XE:
  1604.     case _XE:
  1605.     case SIN:
  1606.     case _SIN:
  1607.     case SHIN:
  1608.     case _SHIN:
  1609.     case SAD:
  1610.     case _SAD:
  1611.     case ZAD:
  1612.     case _ZAD:
  1613.     case _TA:
  1614.     case _ZA:
  1615.     case AYN:
  1616.     case _AYN:
  1617.     case _AYN_:
  1618.     case AYN_:
  1619.     case GHAYN:
  1620.     case GHAYN_:
  1621.     case _GHAYN_:
  1622.     case _GHAYN:
  1623.     case FE:
  1624.     case _FE:
  1625.     case GHAF:
  1626.     case _GHAF:
  1627.     case _KAF_H:
  1628.     case KAF:
  1629.     case _KAF:
  1630.     case GAF:
  1631.     case _GAF:
  1632.     case LAM:
  1633.     case _LAM:
  1634.     case MIM:
  1635.     case _MIM:
  1636.     case NOON:
  1637.     case _NOON:
  1638.     case IE:
  1639.     case _IE:
  1640.     case IE_:
  1641.     case YE:
  1642.     case _YE:
  1643.     case YE_:
  1644.     case YEE:
  1645.     case _YEE:
  1646.     case YEE_:
  1647.     case F_HE:
  1648.     case _HE:
  1649.     case _HE_:
  1650.         return TRUE;
  1651.     }
  1652.     return FALSE;
  1653. }
  1654.  
  1655. /*
  1656. ** Can a given Farsi character join via its right edj.
  1657. */
  1658.     static int
  1659. canF_Rjoin(c)
  1660.     int        c;
  1661. {
  1662.     switch (c)
  1663.     {
  1664.     case ALEF:
  1665.     case ALEF_:
  1666.     case ALEF_U_H:
  1667.     case ALEF_U_H_:
  1668.     case DAL:
  1669.     case ZAL:
  1670.     case RE:
  1671.     case JE:
  1672.     case ZE:
  1673.     case TEE:
  1674.     case TEE_:
  1675.     case WAW:
  1676.     case WAW_H:
  1677.         return TRUE;
  1678.     }
  1679.  
  1680.     return canF_Ljoin(c);
  1681.  
  1682. }
  1683.  
  1684. /*
  1685. ** is a given Farsi character a terminating type.
  1686. */
  1687.     static int
  1688. F_isterm(c)
  1689.     int        c;
  1690. {
  1691.     switch (c)
  1692.     {
  1693.     case ALEF:
  1694.     case ALEF_:
  1695.     case ALEF_U_H:
  1696.     case ALEF_U_H_:
  1697.     case DAL:
  1698.     case ZAL:
  1699.     case RE:
  1700.     case JE:
  1701.     case ZE:
  1702.     case WAW:
  1703.     case WAW_H:
  1704.     case TEE:
  1705.     case TEE_:
  1706.         return TRUE;
  1707.     }
  1708.  
  1709.     return FALSE;
  1710. }
  1711.  
  1712. /*
  1713. ** Convert the given Farsi character into a ending type .
  1714. */
  1715.     static int
  1716. toF_ending(c)
  1717.     int        c;
  1718. {
  1719.  
  1720.     switch (c)
  1721.     {
  1722.     case _BE:
  1723.         return BE;
  1724.     case _PE:
  1725.         return PE;
  1726.     case _TE:
  1727.         return TE;
  1728.     case _SE:
  1729.         return SE;
  1730.     case _JIM:
  1731.         return JIM;
  1732.     case _CHE:
  1733.         return CHE;
  1734.     case _HE_J:
  1735.         return HE_J;
  1736.     case _XE:
  1737.         return XE;
  1738.     case _SIN:
  1739.         return SIN;
  1740.     case _SHIN:
  1741.         return SHIN;
  1742.     case _SAD:
  1743.         return SAD;
  1744.     case _ZAD:
  1745.         return ZAD;
  1746.     case _AYN:
  1747.         return AYN;
  1748.     case _AYN_:
  1749.         return AYN_;
  1750.     case _GHAYN:
  1751.         return GHAYN;
  1752.     case _GHAYN_:
  1753.         return GHAYN_;
  1754.     case _FE:
  1755.         return FE;
  1756.     case _GHAF:
  1757.         return GHAF;
  1758.     case _KAF_H:
  1759.     case _KAF:
  1760.         return KAF;
  1761.     case _GAF:
  1762.         return GAF;
  1763.     case _LAM:
  1764.         return LAM;
  1765.     case _MIM:
  1766.         return MIM;
  1767.     case _NOON:
  1768.         return NOON;
  1769.     case _YE:
  1770.         return YE_;
  1771.     case YE_:
  1772.         return YE;
  1773.     case _YEE:
  1774.         return YEE_;
  1775.     case YEE_:
  1776.         return YEE;
  1777.     case TEE:
  1778.         return TEE_;
  1779.     case _IE:
  1780.         return IE_;
  1781.     case IE_:
  1782.         return IE;
  1783.     case _HE:
  1784.     case _HE_:
  1785.         return F_HE;
  1786.     }
  1787.     return c;
  1788. }
  1789.  
  1790. /*
  1791. ** Convert the Farsi 3342 standard into Farsi VIM.
  1792. */
  1793.     void
  1794. conv_to_pvim()
  1795. {
  1796.     char_u    *ptr;
  1797.     int        lnum, llen, i;
  1798.  
  1799.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
  1800.     {
  1801.     ptr = ml_get((linenr_T)lnum);
  1802.  
  1803.     llen = (int)STRLEN(ptr);
  1804.  
  1805.     for ( i = 0; i < llen-1; i++)
  1806.     {
  1807.         if (canF_Ljoin(ptr[i]) && canF_Rjoin(ptr[i+1]))
  1808.         {
  1809.         ptr[i] = toF_leading(ptr[i]);
  1810.         ++i;
  1811.  
  1812.         while(canF_Rjoin(ptr[i]) && (i < llen))
  1813.         {
  1814.             ptr[i] = toF_Rjoin(ptr[i]);
  1815.             if (F_isterm(ptr[i]) || !F_isalpha(ptr[i]))
  1816.             break;
  1817.             ++i;
  1818.         }
  1819.         if (!F_isalpha(ptr[i]) || !canF_Rjoin(ptr[i]))
  1820.             ptr[i-1] = toF_ending(ptr[i-1]);
  1821.         }
  1822.         else
  1823.         ptr[i] = toF_TyA(ptr[i]);
  1824.     }
  1825.     }
  1826.  
  1827.     /*
  1828.      * Following lines contains Farsi encoded character.
  1829.      */
  1830.  
  1831.     do_cmdline_cmd((char_u *)"%s/\202\231/\232/g");
  1832.     do_cmdline_cmd((char_u *)"%s/\201\231/\370\334/g");
  1833.  
  1834.     /* Assume the screen has been messed up: clear it and redraw. */
  1835.     redraw_later(CLEAR);
  1836.     MSG_ATTR(farsi_text_1, hl_attr(HLF_S));
  1837. }
  1838.  
  1839. /*
  1840.  * Convert the Farsi VIM into Farsi 3342 standad.
  1841.  */
  1842.     void
  1843. conv_to_pstd()
  1844. {
  1845.     char_u    *ptr;
  1846.     int        lnum, llen, i;
  1847.  
  1848.     /*
  1849.      * Following line contains Farsi encoded character.
  1850.      */
  1851.  
  1852.     do_cmdline_cmd((char_u *)"%s/\232/\202\231/g");
  1853.  
  1854.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
  1855.     {
  1856.     ptr = ml_get((linenr_T)lnum);
  1857.  
  1858.     llen = (int)STRLEN(ptr);
  1859.  
  1860.     for ( i = 0; i < llen; i++)
  1861.     {
  1862.         ptr[i] = toF_TyA(ptr[i]);
  1863.  
  1864.     }
  1865.     }
  1866.  
  1867.     /* Assume the screen has been messed up: clear it and redraw. */
  1868.     redraw_later(CLEAR);
  1869.     MSG_ATTR(farsi_text_2, hl_attr(HLF_S));
  1870. }
  1871.  
  1872. /*
  1873.  * left-right swap the characters in buf[len].
  1874.  */
  1875.     static void
  1876. lrswapbuf(buf, len)
  1877.     char_u    *buf;
  1878.     int        len;
  1879. {
  1880.     char_u    *s, *e;
  1881.     int        c;
  1882.  
  1883.     s = buf;
  1884.     e = buf + len - 1;
  1885.  
  1886.     while (e > s)
  1887.     {
  1888.     c = *s;
  1889.     *s = *e;
  1890.     *e = c;
  1891.     ++s;
  1892.     --e;
  1893.     }
  1894. }
  1895.  
  1896. /*
  1897.  * swap all the characters in reverse direction
  1898.  */
  1899.     char_u *
  1900. lrswap(ibuf)
  1901.     char_u    *ibuf;
  1902. {
  1903.     if (ibuf != NULL && *ibuf != NUL)
  1904.     lrswapbuf(ibuf, (int)STRLEN(ibuf));
  1905.     return ibuf;
  1906. }
  1907.  
  1908. /*
  1909.  * swap all the Farsi characters in reverse direction
  1910.  */
  1911.     char_u *
  1912. lrFswap(cmdbuf, len)
  1913.     char_u    *cmdbuf;
  1914.     int        len;
  1915. {
  1916.     int        i, cnt;
  1917.  
  1918.     if (cmdbuf == NULL)
  1919.     return cmdbuf;
  1920.  
  1921.     if (len == 0 && (len = (int)STRLEN(cmdbuf)) == 0)
  1922.     return cmdbuf;
  1923.  
  1924.     for (i = 0; i < len; i++)
  1925.     {
  1926.     for (cnt = 0; i + cnt < len
  1927.             && (F_isalpha(cmdbuf[i + cnt])
  1928.                 || F_isdigit(cmdbuf[i + cnt])
  1929.                 || cmdbuf[i + cnt] == ' '); ++cnt)
  1930.         ;
  1931.  
  1932.     lrswapbuf(cmdbuf + i, cnt);
  1933.     i += cnt;
  1934.     }
  1935.     return cmdbuf;
  1936. }
  1937.  
  1938. /*
  1939.  * Reverse the characters in the seach path and substitude section accordingly
  1940.  */
  1941.     char_u *
  1942. lrF_sub(ibuf)
  1943.     char_u    *ibuf;
  1944. {
  1945.     char_u    *p, *ep;
  1946.     int        i, cnt;
  1947.  
  1948.     p = ibuf;
  1949.  
  1950.     /* Find the boundry of the search path */
  1951.     while (((p = vim_strchr(++p, '/')) != NULL) && p[-1] == '\\')
  1952.     ;
  1953.  
  1954.     if (p == NULL)
  1955.     return ibuf;
  1956.  
  1957.     /* Reverse the Farsi characters in the search path. */
  1958.     lrFswap(ibuf, (int)(p-ibuf));
  1959.  
  1960.     /* Now find the boundry of the substitute section */
  1961.     if ((ep = (char_u *)strrchr((char *)++p, '/')) != NULL)
  1962.     cnt = (int)(ep - p);
  1963.     else
  1964.     cnt = (int)STRLEN(p);
  1965.  
  1966.     /* Reverse the characters in the substitute section and take care of '\' */
  1967.     for (i = 0; i < cnt-1; i++)
  1968.     if (p[i] == '\\')
  1969.     {
  1970.         p[i] = p[i+1] ;
  1971.         p[++i] = '\\';
  1972.     }
  1973.  
  1974.     lrswapbuf(p, cnt);
  1975.  
  1976.     return ibuf;
  1977. }
  1978.  
  1979. /*
  1980.  * Map Farsi keyboard when in cmd_fkmap mode.
  1981.  */
  1982.     int
  1983. cmdl_fkmap(c)
  1984.     int c;
  1985. {
  1986.     int        tempc;
  1987.  
  1988.     switch (c)
  1989.     {
  1990.     case '0':
  1991.     case '1':
  1992.     case '2':
  1993.     case '3':
  1994.     case '4':
  1995.     case '5':
  1996.     case '6':
  1997.     case '7':
  1998.     case '8':
  1999.     case '9':
  2000.     case '`':
  2001.     case ' ':
  2002.     case '.':
  2003.     case '!':
  2004.     case '"':
  2005.     case '$':
  2006.     case '%':
  2007.     case '^':
  2008.     case '&':
  2009.     case '/':
  2010.     case '(':
  2011.     case ')':
  2012.     case '=':
  2013.     case '\\':
  2014.     case '?':
  2015.     case '+':
  2016.     case '-':
  2017.     case '_':
  2018.     case '*':
  2019.     case ':':
  2020.     case '#':
  2021.     case '~':
  2022.     case '@':
  2023.     case '<':
  2024.     case '>':
  2025.     case '{':
  2026.     case '}':
  2027.     case '|':
  2028.     case 'B':
  2029.     case 'E':
  2030.     case 'F':
  2031.     case 'H':
  2032.     case 'I':
  2033.     case 'K':
  2034.     case 'L':
  2035.     case 'M':
  2036.     case 'O':
  2037.     case 'P':
  2038.     case 'Q':
  2039.     case 'R':
  2040.     case 'T':
  2041.     case 'U':
  2042.     case 'W':
  2043.     case 'Y':
  2044.     case  NL:
  2045.     case  TAB:
  2046.  
  2047.            switch ((tempc = cmd_gchar(AT_CURSOR)))
  2048.            {
  2049.         case _BE:
  2050.         case _PE:
  2051.         case _TE:
  2052.         case _SE:
  2053.         case _JIM:
  2054.         case _CHE:
  2055.         case _HE_J:
  2056.         case _XE:
  2057.         case _SIN:
  2058.         case _SHIN:
  2059.         case _SAD:
  2060.         case _ZAD:
  2061.         case _AYN:
  2062.         case _GHAYN:
  2063.         case _FE:
  2064.         case _GHAF:
  2065.         case _KAF:
  2066.         case _GAF:
  2067.         case _LAM:
  2068.         case _MIM:
  2069.         case _NOON:
  2070.         case _HE:
  2071.         case _HE_:
  2072.             cmd_pchar(toF_TyA(tempc), AT_CURSOR);
  2073.         break;
  2074.         case _AYN_:
  2075.             cmd_pchar(AYN_, AT_CURSOR);
  2076.         break;
  2077.         case _GHAYN_:
  2078.             cmd_pchar(GHAYN_, AT_CURSOR);
  2079.         break;
  2080.         case _IE:
  2081.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
  2082.                 cmd_pchar(IE_, AT_CURSOR);
  2083.         else
  2084.                 cmd_pchar(IE, AT_CURSOR);
  2085.         break;
  2086.         case _YEE:
  2087.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
  2088.                 cmd_pchar(YEE_, AT_CURSOR);
  2089.             else
  2090.                 cmd_pchar(YEE, AT_CURSOR);
  2091.         break;
  2092.         case _YE:
  2093.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
  2094.                 cmd_pchar(YE_, AT_CURSOR);
  2095.             else
  2096.                 cmd_pchar(YE, AT_CURSOR);
  2097.         }
  2098.  
  2099.         switch (c)
  2100.         {
  2101.         case '0':   return FARSI_0;
  2102.         case '1':   return FARSI_1;
  2103.         case '2':   return FARSI_2;
  2104.         case '3':   return FARSI_3;
  2105.         case '4':   return FARSI_4;
  2106.         case '5':   return FARSI_5;
  2107.         case '6':   return FARSI_6;
  2108.         case '7':   return FARSI_7;
  2109.         case '8':   return FARSI_8;
  2110.         case '9':   return FARSI_9;
  2111.         case 'B':   return F_PSP;
  2112.         case 'E':   return JAZR_N;
  2113.         case 'F':   return ALEF_D_H;
  2114.         case 'H':   return ALEF_A;
  2115.         case 'I':   return TASH;
  2116.         case 'K':   return F_LQUOT;
  2117.         case 'L':   return F_RQUOT;
  2118.         case 'M':   return HAMZE;
  2119.         case 'O':   return '[';
  2120.         case 'P':   return ']';
  2121.         case 'Q':   return OO;
  2122.         case 'R':   return MAD_N;
  2123.         case 'T':   return OW;
  2124.         case 'U':   return MAD;
  2125.         case 'W':   return OW_OW;
  2126.         case 'Y':   return JAZR;
  2127.         case '`':   return F_PCN;
  2128.         case '!':   return F_EXCL;
  2129.         case '@':   return F_COMMA;
  2130.         case '#':   return F_DIVIDE;
  2131.         case '$':   return F_CURRENCY;
  2132.         case '%':   return F_PERCENT;
  2133.         case '^':   return F_MUL;
  2134.         case '&':   return F_BCOMMA;
  2135.         case '*':   return F_STAR;
  2136.         case '(':   return F_LPARENT;
  2137.         case ')':   return F_RPARENT;
  2138.         case '-':   return F_MINUS;
  2139.         case '_':   return F_UNDERLINE;
  2140.         case '=':   return F_EQUALS;
  2141.         case '+':   return F_PLUS;
  2142.         case '\\':  return F_BSLASH;
  2143.         case '|':   return F_PIPE;
  2144.         case ':':   return F_DCOLON;
  2145.         case '"':   return F_SEMICOLON;
  2146.         case '.':   return F_PERIOD;
  2147.         case '/':   return F_SLASH;
  2148.         case '<':   return F_LESS;
  2149.         case '>':   return F_GREATER;
  2150.         case '?':   return F_QUESTION;
  2151.         case ' ':   return F_BLANK;
  2152.         }
  2153.  
  2154.         break;
  2155.  
  2156.     case 'a':   return _SHIN;
  2157.     case 'A':   return WAW_H;
  2158.     case 'b':   return ZAL;
  2159.     case 'c':   return ZE;
  2160.     case 'C':   return JE;
  2161.     case 'd':   return _YE;
  2162.     case 'D':   return _YEE;
  2163.     case 'e':   return _SE;
  2164.     case 'f':   return _BE;
  2165.     case 'g':   return _LAM;
  2166.     case 'G':
  2167.             if (cmd_gchar(AT_CURSOR) == _LAM )
  2168.         {
  2169.             cmd_pchar(LAM, AT_CURSOR);
  2170.                 return ALEF_U_H;
  2171.         }
  2172.  
  2173.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2174.             return ALEF_U_H_;
  2175.         else
  2176.             return ALEF_U_H;
  2177.     case 'h':
  2178.             if (cmd_gchar(AT_CURSOR) == _LAM )
  2179.         {
  2180.             cmd_pchar(LA, AT_CURSOR);
  2181.             redrawcmdline();
  2182.             return K_IGNORE;
  2183.         }
  2184.  
  2185.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2186.             return ALEF_;
  2187.         else
  2188.             return ALEF;
  2189.     case 'i':
  2190.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2191.             return _HE_;
  2192.         else
  2193.             return _HE;
  2194.     case 'j':   return _TE;
  2195.     case 'J':
  2196.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2197.             return TEE_;
  2198.         else
  2199.             return TEE;
  2200.     case 'k':   return _NOON;
  2201.     case 'l':   return _MIM;
  2202.     case 'm':   return _PE;
  2203.     case 'n':
  2204.     case 'N':   return DAL;
  2205.     case 'o':   return _XE;
  2206.     case 'p':   return _HE_J;
  2207.     case 'q':   return _ZAD;
  2208.     case 'r':   return _GHAF;
  2209.     case 's':   return _SIN;
  2210.     case 'S':   return _IE;
  2211.     case 't':   return _FE;
  2212.     case 'u':
  2213.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2214.             return _AYN_;
  2215.         else
  2216.             return _AYN;
  2217.     case 'v':
  2218.     case 'V':   return RE;
  2219.     case 'w':   return _SAD;
  2220.     case 'x':
  2221.     case 'X':   return _TA;
  2222.     case 'y':
  2223.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2224.             return _GHAYN_;
  2225.         else
  2226.             return _GHAYN;
  2227.     case 'z':
  2228.     case 'Z':   return _ZA;
  2229.     case ';':   return _KAF;
  2230.     case '\'':  return _GAF;
  2231.     case ',':   return WAW;
  2232.     case '[':   return _JIM;
  2233.     case ']':   return _CHE;
  2234.     }
  2235.  
  2236.     return c;
  2237. }
  2238.  
  2239. /*
  2240.  * F_isalpha returns TRUE if 'c' is a Farsi alphabet
  2241.  */
  2242.     int
  2243. F_isalpha(c)
  2244.     int    c;
  2245. {
  2246.     return (( c >= TEE_ && c <= _YE)
  2247.         || (c >= ALEF_A && c <= YE)
  2248.         || (c >= _IE && c <= YE_));
  2249. }
  2250.  
  2251. /*
  2252.  * F_isdigit returns TRUE if 'c' is a Farsi digit
  2253.  */
  2254.     int
  2255. F_isdigit(c)
  2256.     int    c;
  2257. {
  2258.     return (c >= FARSI_0 && c <= FARSI_9);
  2259. }
  2260.  
  2261. /*
  2262.  * F_ischar returns TRUE if 'c' is a Farsi character.
  2263.  */
  2264.     int
  2265. F_ischar(c)
  2266.     int    c;
  2267. {
  2268.     return (c >= TEE_ && c <= YE_);
  2269. }
  2270.  
  2271.     void
  2272. farsi_fkey(cap)
  2273.     cmdarg_T    *cap;
  2274. {
  2275.     int        c = cap->cmdchar;
  2276.  
  2277.     if (c == K_F8)
  2278.     {
  2279.     if (p_altkeymap)
  2280.     {
  2281.         if (curwin->w_farsi & W_R_L)
  2282.         {
  2283.         p_fkmap = 0;
  2284.         do_cmdline_cmd((char_u *)"set norl");
  2285.         MSG("");
  2286.         }
  2287.         else
  2288.         {
  2289.         p_fkmap = 1;
  2290.         do_cmdline_cmd((char_u *)"set rl");
  2291.         MSG("");
  2292.         }
  2293.  
  2294.         curwin->w_farsi = curwin->w_farsi ^ W_R_L;
  2295.     }
  2296.     }
  2297.  
  2298.     if (c == K_F9)
  2299.     {
  2300.     if (p_altkeymap && curwin->w_p_rl)
  2301.     {
  2302.         curwin->w_farsi = curwin->w_farsi ^ W_CONV;
  2303.         if (curwin->w_farsi & W_CONV)
  2304.         conv_to_pvim();
  2305.         else
  2306.         conv_to_pstd();
  2307.     }
  2308.     }
  2309. }
  2310.